﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using QuadRemote.Core;

namespace QuadRemote.Tabs
{
    public partial class GraphPanel : UserControl
    {
        int start;
        int end;

        List<GraphFrame> graphFrames;

        public GraphPanel()
        {
            InitializeComponent();

            graphFrames = new List<GraphFrame>();

            start = 0;
            end = 1000;

            GraphFrame n = newGraphFrame();
            table.Controls.Add(n, 1, 0);
            graphFrames.Add(n);

            loadSavedGraphs();
        }

        public GraphFrame newGraphFrame()
        {
            GraphFrame g = new GraphFrame() { Dock = DockStyle.Fill };
            g.SetTime(start, end);
            g.GraphChanged += GraphChanged;
            return g;
        }

        void GraphChanged(GraphFrame sender, int start, int end)
        {
            foreach (GraphFrame frame in getGraphFrames())
            {
                if (frame != sender)
                {
                    frame.SetTime(start, end);
                }
            }

            this.start = start;
            this.end = end;
        }

        private List<GraphFrame> getGraphFrames()
        {
            return graphFrames;
        }

/*        private GraphFrame getGraphFrameAt(int x, int y)
        {
            foreach (GraphFrame in table.Controls)
            {
                if (table.GetColumn(ctrl) == x+1 && table.GetRow(ctrl) == y)
                    return (GraphFrame)ctrl;
            }

            return null;
        }*/

        private void btRowAdd_Click(object sender, EventArgs e)
        {
            table.RowCount = table.RowCount + 1;
            table.RowStyles.Add(new RowStyle(SizeType.AutoSize));
            Console.WriteLine("Row = " + table.RowCount);
            table.SetRowSpan(sideTable, table.RowCount);

            for (int i = 0; i < table.ColumnCount - 1; i++)
            {
                GraphFrame n = newGraphFrame();
                table.Controls.Add(n, i + 1, table.RowCount - 1);
                Console.WriteLine("Graph add " + table.GetRow(n) + "," + table.GetColumn(n));
                graphFrames.Insert(i * 2 + table.RowCount-1, n);
            }
        }

        private void btColAdd_Click(object sender, EventArgs e)
        {
            table.ColumnCount = table.ColumnCount + 1;
            table.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));

            Console.WriteLine("Col = " + table.ColumnCount);

            for (int i = 0; i < table.RowCount; i++)
            {
                GraphFrame n = newGraphFrame();
                table.Controls.Add(n, table.ColumnCount - 1, i);
                Console.WriteLine("Graph add " + table.GetRow(n) + "," + table.GetColumn(n));
                graphFrames.Add(n);
            }
        }

        private void table_Paint(object sender, PaintEventArgs e)
        {

        }

        private void table_ControlAdded(object sender, ControlEventArgs e)
        {
            //return;
            Console.WriteLine("ControlAdded");
            Boolean first = true;
            foreach (ColumnStyle rs in table.ColumnStyles)
            {
                if (first) { first = false; continue; }
                rs.SizeType = SizeType.Percent;
                rs.Width = 100; // / (table.ColumnCount - 1);
            }

            foreach (RowStyle rs in table.RowStyles)
            {
                rs.SizeType = SizeType.Percent;
                rs.Height = 100; // / (table.RowCount);
            }
        }

        private void btRowDel_Click(object sender, EventArgs e)
        {
            if (table.RowCount == 1) return;

            for (int i = 0; i < table.ColumnCount - 1;i++)
            {
                GraphFrame f = graphFrames[i + table.RowCount - 1];
                Console.WriteLine("Graph del " + table.GetRow(f) + "," + table.GetColumn(f));
                graphFrames.Remove(f);
                table.Controls.Remove(f);
            }

            table.RowCount--;
            table.RowStyles.RemoveAt(table.RowStyles.Count - 1);
            table_ControlAdded(null, null);
            table.SetRowSpan(sideTable, table.RowCount);
        }

        private void btColDel_Click(object sender, EventArgs e)
        {
            if (table.ColumnCount == 2) return;

            for (int i = 0; i < table.RowCount; i++)
            {
                GraphFrame f = graphFrames[graphFrames.Count - 1];
                Console.WriteLine("Graph del " + table.GetRow(f) + "," + table.GetColumn(f));
                graphFrames.Remove(f);
                table.Controls.Remove(f);
            }

            table.ColumnCount--;
            table.ColumnStyles.RemoveAt(table.ColumnStyles.Count - 1);

            table_ControlAdded(null, null);
        }

        private void label1_Click(object sender, EventArgs e)
        {

        }

        private void btSave_Click(object sender, EventArgs e)
        {
            Random r = new Random();
            String n = txtName.Text;
            if (n == "") n = "Noname";

            delGraph(n);

            String s = Properties.Settings.Default.Graphs;

            XmlDocument xml = new XmlDocument();
            xml.Load(new System.IO.StringReader(s));

            XmlElement root = xml.DocumentElement;

            root.AppendChild(save(xml, n));

            Properties.Settings.Default.Graphs = xml.OuterXml;
            Properties.Settings.Default.Save();
            loadSavedGraphs();

        }

        XmlElement save(XmlDocument root, String name)
        {
            XmlElement node = (XmlElement)root.CreateElement("graph");
            node.AppendChild(root.CreateElement("name")).InnerText = name;
            node.AppendChild(root.CreateElement("gridX")).InnerText = (table.ColumnCount - 1).ToString();
            node.AppendChild(root.CreateElement("gridY")).InnerText = table.RowCount.ToString();

            XmlElement subs = (XmlElement)node.AppendChild(root.CreateElement("subs"));

            foreach (GraphFrame frame in getGraphFrames())
            {
                subs.AppendChild(frame.save(root));
            }

            return node;
        }

        void loadSavedGraphs()
        {
            String s = Properties.Settings.Default.Graphs;

            XmlDocument xml = new XmlDocument();
            xml.Load(new System.IO.StringReader(s));

            XmlElement root = xml.DocumentElement;

            lstSaved.Items.Clear();
            foreach (XmlNode node in root.ChildNodes)
            {
                //Console.WriteLine(node.OuterXml);
                String name = node.SelectSingleNode("name").InnerText;
                lstSaved.Items.Add(name);
            }
        }

        void delGraph(String name)
        {
            String s = Properties.Settings.Default.Graphs;
            XmlDocument xml = new XmlDocument();
            xml.Load(new System.IO.StringReader(s));

            XmlElement root = xml.DocumentElement;

            foreach (XmlNode node in root.ChildNodes)
            {
                //Console.WriteLine(node.OuterXml);
                String nodename = node.SelectSingleNode("name").InnerText;

                if (nodename == name)
                {
                    root.RemoveChild(node);
                }
            }

            Properties.Settings.Default.Graphs = xml.OuterXml;
            Properties.Settings.Default.Save();
            loadSavedGraphs();
        }

        void loadGraph(String name)
        {
            String s = Properties.Settings.Default.Graphs;

            txtName.Text = name;

            XmlDocument xml = new XmlDocument();
            xml.Load(new System.IO.StringReader(s));

            XmlElement root = xml.DocumentElement;

            foreach (XmlNode node in root.ChildNodes)
            {
                String nodename = node.SelectSingleNode("name").InnerText;
                if (name == nodename)
                {
                    int gx = int.Parse(node.SelectSingleNode("gridX").InnerText);
                    int gy = int.Parse(node.SelectSingleNode("gridY").InnerText);

                    while (gx > table.ColumnCount - 1)
                        btColAdd_Click(null, null);
                    while (gx < table.ColumnCount - 1)
                        btColDel_Click(null, null);
                    while (gy > table.RowCount)
                        btRowAdd_Click(null, null);
                    while (gy < table.RowCount)
                        btRowDel_Click(null, null);

                    //Console.WriteLine(node.OuterXml);
                    XmlNodeList graphs = node.SelectSingleNode("subs").ChildNodes;
                    Console.WriteLine(graphs.Count);
                    int i = 0;
                    List<GraphFrame> frames = getGraphFrames();
                    foreach (XmlNode g in graphs)
                    {
                        Console.WriteLine("-- " + i + "  ==>  " + g.OuterXml);
                        frames[i++].loadXml(g);
                    }
                }
            }
        }

        private void btDel_Click(object sender, EventArgs e)
        {
            delGraph(txtName.Text);
        }

        private void lstSaved_DoubleClick(object sender, EventArgs e)
        {
            if (lstSaved.SelectedIndex < 0) return;
            try
            {
                loadGraph((String)lstSaved.Items[lstSaved.SelectedIndex]);
            }
            catch (Exception ee)
            {
                MessageBox.Show("Error while loading graphs: " + ee.Message);
            }
        }

        private void trackBar1_Scroll(object sender, EventArgs e)
        {
            setRealtimeValues();
        }

        int[] realtimeLookup = new int[] { 0, 1, 5, 10, 25, 50, 75, 100, 250, 500, 1000 };

        void setRealtimeValues()
        {
            int ticks = 0;
            if (tbRealtime.Value > 0)
            {
                ticks = 1000 / realtimeLookup[tbRealtime.Value];
            }

            byte[] packet = new byte[FlightSession.current().Log.values.Count * 3];

            int pos = 0;
            foreach (GraphFrame f in getGraphFrames())
            {
                foreach (LogValueGraph g in f.plots)
                {
                    int id = (int)g.container.id;
                    packet[pos++] = (byte)g.container.id;
                    packet[pos++] = (byte)(ticks >> 8);
                    packet[pos++] = (byte)(ticks);
                }
            }

            new CommandOut(CommandId.CMD_LOG_SET_INTERVAL, packet).send();

            Console.WriteLine(Tools.getHexString(packet));

            //Bluetooth.instance().sendPriorityPacket(packet);
        }

        private void lstSaved_SelectedIndexChanged(object sender, EventArgs e)
        {

        }
    }
}
